# pragma once

# include "serialib.h"
# include "socat_manager.h"

class serial_player
{
private:
    serialib serial;

    const std::string virtualTx = "/tmp/virtual_tx";
    const std::string virtualRx = "/tmp/virtual_rx";
    const unsigned int baudRate = 115200;
    const std::string logFile;

    std::vector<std::pair<double, std::vector<unsigned char>>> dataQueue;
public:
    /// @brief 
    /// @param arg1 virtualTx
    /// @param arg2 virtualRx
    /// @param arg3 baudRate
    /// @param arg4 logFile
    serial_player(std::string arg1, std::string arg2, unsigned int arg3, std::string arg4)
        : virtualTx(arg1), virtualRx(arg2), baudRate(arg3), logFile(arg4)
    {
        startSocat(virtualTx, virtualRx);
        
        int serialResult = serial.openDevice(
            virtualTx.c_str(), 
            baudRate, 
            SERIAL_DATABITS_8,
            SERIAL_PARITY_NONE,
            SERIAL_STOPBITS_1
        );

        if (serialResult != 1) 
        {
            stopSocat(virtualTx, virtualRx);

            throw std::runtime_error("无法打开虚拟串口 " + virtualTx);
        }

        std::cout << "已连接虚拟发送串口: " << virtualTx << " 波特率: " << baudRate << std::endl;

        std::ifstream logStream(logFile);
        if (!logStream.is_open()) 
        {
            serial.closeDevice();
            stopSocat(virtualTx, virtualRx);

            throw std::runtime_error("无法打开日志文件: " + logFile);
        }
        std::cout << "正在读取日志文件: " << logFile << std::endl;
        
        // 存储时间戳和对应的二进制数据
        std::string line;
        size_t invalidLineCount = 0;
        
        while (std::getline(logStream, line)) 
        {
            double timestamp;
            std::vector<unsigned char> binaryData;
            if (parseLogLine(line, timestamp, binaryData)) 
            {
                dataQueue.emplace_back(timestamp, binaryData);
            } 
            else 
            {
                invalidLineCount++;
            }
        }
        logStream.close();

        if (invalidLineCount > 0) 
        {
            std::cerr << "警告: 日志中共有 " << invalidLineCount << " 行无效格式，已忽略" << std::endl;
        }
        
        if (dataQueue.empty()) 
        {
            serial.closeDevice();
            stopSocat(virtualTx, virtualRx);

            throw std::runtime_error("日志文件中没有有效数据");
        }
        
        std::cout << "已加载 " << dataQueue.size() << " 条数据，准备播放..." << std::endl;
        std::cout << "请在应用程序中连接接收端串口: " << virtualRx << std::endl;
    };

    ~serial_player()
    {
        serial.closeDevice();
        stopSocat(virtualTx, virtualRx);
    };

    void play(std::chrono::_V2::system_clock::time_point startTime, double prevTimestamp)
    {
        size_t sentCount = 0;
        std::chrono::duration<double> duration(0);
        
        for (const auto& entry : dataQueue) 
        {
            double currentTimestamp = entry.first;
            const std::vector<unsigned char>& binaryData = entry.second;
            
            // 按时间间隔等待
            duration += std::chrono::duration<double>(currentTimestamp - prevTimestamp);
            std::this_thread::sleep_until(duration + startTime);

            // 发送二进制数据
            int bytesSent = serial.writeBytes(reinterpret_cast<const char*>(binaryData.data()), binaryData.size());
            if (bytesSent > 0) 
            {
                sentCount++;

                // 控制台输出十六进制（方便查看）
                std::cout << "[" << currentTimestamp << " (" << sentCount << ")" << virtualRx << "] 发送 (hex): ";

                for (unsigned char c : binaryData) {
                    std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(c);
                }

                std::cout << std::dec << " (" << bytesSent << "字节)" << std::endl;
            } 
            else 
            {
                std::cerr << "[" << currentTimestamp << "] 发送失败" << std::endl;
            }
            
            prevTimestamp = currentTimestamp;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        std::cout << "播放完成，共发送 " << sentCount << " 条数据" << std::endl;
    }

    double getFirstTimestamp() const
    {
        return dataQueue[0].first;
    }

    serial_player(const serial_player&) = delete;
    serial_player operator = (const serial_player&) = delete;
};